package com.jevons.geo_edit.activity;

import android.animation.Animator;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.animation.ValueAnimator;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;

import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;

import com.jevons.geo_edit.R;
import com.jevons.geo_edit.constant.GisGeometryType;
import com.jevons.geo_edit.databinding.ActivityGisMapBinding;
import com.jevons.geo_edit.event.GisMapLayerOpEvent;
import com.jevons.geo_edit.fragment.GisOpHistoryFragment;
import com.jevons.geo_edit.listner.SimpleAnimatorListener;
import com.jevons.geo_edit.model.GisOpHistory;
import com.jevons.geo_edit.view.GisMapView;
import com.jevons.geo_lib.op_history.DrawType;
import com.jevons.geo_lib.view.BaseMapView;
import com.jevons.muffin.eventbus.CustomEvent;
import com.jevons.muffin.util.SysSharePres;
import com.jevons.muffin.utilcode.LogUtils;
import com.jevons.muffin.widget.alertView.AlertView;
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.maps.Style;
import com.mapbox.mapboxsdk.style.layers.Layer;
import com.mapbox.turf.TurfConstants;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

/**
 * Copyright 2020 JxGIS
 *
 * @file GisMapActivity
 * @auth linaisheng
 * Created on 2024/5/16.
 * Description：
 */
public class GisMapActivity extends BaseBindingActivity<ActivityGisMapBinding, GisMapViewModel, GisMapPresenter>
        implements GisMapView, BaseMapView {

    private MapboxMap mMapBoxMap;
    private Style loadStyle;

    @Override
    protected int setLayout() {
        return R.layout.activity_gis_map;
    }

    @Override
    protected Class getViewModelClz() {
        return GisMapViewModel.class;
    }

    @Override
    protected GisMapPresenter initPresenter() {
        return new GisMapPresenter();
    }

    @Override
    protected void initView(Bundle savedInstanceState) {
        EventBus.getDefault().register(this);
        dataBinding.setClickHandler(new GeoMapClickHandler());
        dataBinding.setMeasureEventHandler(new MeasureEventHandler());

        dataBinding.mapView.getMapAsync(new OnMapReadyCallback() {
            @Override
            public void onMapReady(@NonNull MapboxMap mapboxMap) {
                mMapBoxMap = mapboxMap;

                //去除水印
                mapboxMap.getUiSettings().setAttributionEnabled(false);

                mapboxMap.getUiSettings().setLogoEnabled(true);
                mapboxMap.getUiSettings().setRotateGesturesEnabled(false);

                mMapBoxMap.setStyle(Style.SATELLITE, new Style.OnStyleLoaded() {
                    @Override
                    public void onStyleLoaded(@NonNull Style style) {
                        loadStyle = style;
                        onMapLoaded();
                    }
                });
            }
        });
    }

    private void onMapLoaded() {
        mPresenter.initMap(this, dataBinding.mapView, mMapBoxMap, loadStyle);

        mMapBoxMap.addOnCameraIdleListener(
                new MapboxMap.OnCameraIdleListener() {
                    @Override
                    public void onCameraIdle() {

                    }
                });
        mMapBoxMap.addOnMapClickListener(new MapboxMap.OnMapClickListener() {
            @Override
            public boolean onMapClick(@NonNull LatLng point) {
                return mPresenter.onMapClick(point);
            }
        });

        String id = getIntent().getStringExtra(KEY_ID);
        String versionId = getIntent().getStringExtra(KEY_VERSION_ID);
        boolean isLocal = getIntent().getBooleanExtra(KEY_IS_LOCAL, false);
        mPresenter.initData(id, versionId, isLocal);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mPresenter.onDestroy();
        EventBus.getDefault().unregister(this);
    }

    @Override
    public void replaceFragment(int viewId, Fragment fragment) {
        getSupportFragmentManager().beginTransaction()
                .replace(viewId, fragment)
                .commit();
    }

    @Override
    public void removeFragment(Fragment fragment) {
        getSupportFragmentManager().beginTransaction()
                .remove(fragment)
                .commit();
    }

    @Override
    public void notifyShowOperationLayout(GisGeometryType geometryType) {
        if (geometryType != GisGeometryType.None) {
            if (geometryType == GisGeometryType.Point) {
                dataBinding.llQiegeBox.setVisibility(View.GONE);
                dataBinding.llWakongBox.setVisibility(View.GONE);
                dataBinding.llHebingBox.setVisibility(View.GONE);
            } else if (geometryType == GisGeometryType.Line) {
                dataBinding.llQiegeBox.setVisibility(View.VISIBLE);
                dataBinding.llWakongBox.setVisibility(View.GONE);
                dataBinding.llHebingBox.setVisibility(View.VISIBLE);
            } else if (geometryType == GisGeometryType.Polygon) {
                dataBinding.llQiegeBox.setVisibility(View.VISIBLE);
                dataBinding.llWakongBox.setVisibility(View.VISIBLE);
                dataBinding.llHebingBox.setVisibility(View.VISIBLE);
            }

            dataBinding.svGeoOpBox.setVisibility(View.VISIBLE);
        } else {
            dataBinding.svGeoOpBox.setVisibility(View.GONE);
        }
    }


    @Override
    public void entryGeoEditModel(DrawType drawType) {
        dataBinding.llGeoListBox.setSelected(false);
        if (drawType == DrawType.None) {
            hideToolLayout();
        } else {
            if (drawType == DrawType.Huizhi) {
                dataBinding.llHuizhiBox.setSelected(true);
            } else if (drawType == DrawType.Bianjie) {
                dataBinding.llBianjieBox.setSelected(true);
            } else if (drawType == DrawType.Qiege) {
                dataBinding.llQiegeBox.setSelected(true);
            } else if (drawType == DrawType.Wakong) {
                dataBinding.llWakongBox.setSelected(true);
            } else if (drawType == DrawType.Hebing) {
                dataBinding.llHebingBox.setSelected(true);
            } else if (drawType == DrawType.Shanchu) {
                dataBinding.llShanchuBox.setSelected(true);
            }


            dataBinding.llCompleteBox.setVisibility(
                    (drawType == DrawType.Huizhi || drawType == DrawType.Qiege
                            || drawType == DrawType.Wakong || drawType == DrawType.Hebing)
                            ? View.VISIBLE : View.GONE
            );
            dataBinding.llSaveBox.setVisibility(
                    (drawType == DrawType.Bianjie || drawType == DrawType.Shanchu)
                            ? View.VISIBLE : View.GONE);
            showToolLayout();
        }
    }

    @Override
    public void existGeoEditModel(DrawType drawType) {
        hideToolLayout();
    }

    @Override
    public void onOpCompleteChange(DrawType drawType, boolean isComplete) {
        dataBinding.llSaveBox.setVisibility(isComplete ? View.VISIBLE : View.GONE);
    }

    @Override
    public void onOpSaveResult(DrawType drawType) {

    }

    @Override
    public void finishWithMsg(String msg) {
        showToast(msg);
        finish();
    }

    @Override
    public void submitSuccess() {
        showToast("提交成功");
        setResult(RESULT_OK);
        finish();
    }

    private void showToolLayout() {
        ValueAnimator animatorLeft = ObjectAnimator.ofPropertyValuesHolder(
                dataBinding.llFormBox,
                PropertyValuesHolder.ofFloat("translationX", 0f, -160f));
        animatorLeft.setDuration(300);
        animatorLeft.addListener(new SimpleAnimatorListener() {
            @Override
            public void onAnimationEnd(Animator animator) {
                dataBinding.llFormBox.setVisibility(View.INVISIBLE);
                ValueAnimator animatorLeft = ObjectAnimator.ofPropertyValuesHolder(
                        dataBinding.llToolOperation,
                        PropertyValuesHolder.ofFloat("translationX", -160f, 0f));
                animatorLeft.setDuration(300);
                animatorLeft.addListener(new SimpleAnimatorListener() {
                    @Override
                    public void onAnimationStart(Animator animator) {
                        dataBinding.llToolOperation.setVisibility(View.VISIBLE);
                    }
                });
                animatorLeft.start();
            }
        });
        animatorLeft.start();
    }

    private void hideToolLayout() {
        dataBinding.llHuizhiBox.setSelected(false);
        dataBinding.llBianjieBox.setSelected(false);
        dataBinding.llQiegeBox.setSelected(false);
        dataBinding.llWakongBox.setSelected(false);
        dataBinding.llHebingBox.setSelected(false);
        dataBinding.llShanchuBox.setSelected(false);

        ValueAnimator animatorLeft = ObjectAnimator.ofPropertyValuesHolder(
                dataBinding.llToolOperation,
                PropertyValuesHolder.ofFloat("translationX", 0f, -160f));
        animatorLeft.setDuration(300);
        animatorLeft.addListener(new SimpleAnimatorListener(){
            @Override
            public void onAnimationEnd(Animator animator) {
                dataBinding.llToolOperation.setVisibility(View.INVISIBLE);
                ValueAnimator animatorLeft = ObjectAnimator.ofPropertyValuesHolder(
                        dataBinding.llFormBox,
                        PropertyValuesHolder.ofFloat("translationX", -160f, 0f));
                animatorLeft.setDuration(300);
                animatorLeft.addListener(new SimpleAnimatorListener(){
                    @Override
                    public void onAnimationStart(Animator animator) {
                        dataBinding.llFormBox.setVisibility(View.VISIBLE);
                    }
                });
                animatorLeft.start();
            }
        });
        animatorLeft.start();
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onMapLayerOpEvent(GisMapLayerOpEvent event) {
        switch (event.getEventFlag()) {
            case GisMapLayerOpEvent.EVENT_CREATE_LAYER:
                mPresenter.addGisLayer(event.getGisLayer());
                break;
            case GisMapLayerOpEvent.EVENT_SELECTED_LAYER:
                mPresenter.notifySelectedLayer(event.getLayerId());
                break;
            case GisMapLayerOpEvent.EVENT_NOTIFY_LAYER_VISIBLE:
                mPresenter.notifyLayerVisible(event.getGisLayer(), true);
                break;
            case GisMapLayerOpEvent.EVENT_NOTIFY_LAYER_INVISIBLE:
                mPresenter.notifyLayerVisible(event.getGisLayer(), false);
                break;
            case GisMapLayerOpEvent.EVENT_SHOW_LAYER_GEOMETRY_LIST:
                mPresenter.showGeometryListDialog(event.getGisLayer());
                break;
            case GisMapLayerOpEvent.EVENT_NOTIFY_LAYER_STYLE_CHANGE:
                mPresenter.notifyLayerStyleChange(event.getGisLayer());
                break;
            case GisMapLayerOpEvent.EVENT_NOTIFY_LAYER_SORT_CHANGE:
                int fromPosition = Integer.parseInt(event.getData("fromPosition"));
                int toPosition = Integer.parseInt(event.getData("toPosition"));
                mPresenter.notifyLayerSortChange(event.getGisLayer(), fromPosition, toPosition);
                break;
            case GisMapLayerOpEvent.EVENT_NOTIFY_LAYER_REMOVE:
                mPresenter.notifyRemoveLayer(event.getLayerId());
                break;
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onCustomEvent(CustomEvent event) {
        if (GisOpHistoryFragment.EVENT_LOAD_OP_HISTORY.equals(event.getCode())) {
            GisOpHistory opHistory = (GisOpHistory) event.getData();
            mPresenter.chooseLoadOpHistory(opHistory.getId());
        } else if (GisOpHistoryFragment.EVENT_LOAD_PROJECT_OPEN_STATE.equals(event.getCode())) {
            mPresenter.chooseLoadOpenProjectData();
        }
    }

    @Override
    public void onBackPressed() {

    }


    @Override
    public void showChooseShareType(String url, String code, String expireTime) {

    }



    public class GeoMapClickHandler {

        public void clickForm(View view) {
            if (view.getId() == R.id.ll_exit_box) {
                if (mPresenter.hadEdit()) {
                    new AlertView.Builder(getContext())
                            .setMessage("有操作未提交！是否继续退出？")
                            .setConfirmButton("提交并退出", new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialogInterface, int i) {
                                    mPresenter.clickConform();
                                }
                            })
                            .setCancelButton("继续退出", new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialogInterface, int i) {
                                    finish();
                                }
                            })
                            .build().show();
                } else {
                    finish();
                }
            } else if (view.getId() == R.id.ll_geo_list_box) {
                boolean isShowing = mPresenter.showLayerManagerDialog();
                dataBinding.llGeoListBox.setSelected(isShowing);
            } else if (view.getId() == R.id.ll_conform_box){
                mPresenter.clickConform();
            }
        }


        public void clickGeoTypeBox(View view) {
            if (view.getId() == R.id.ll_measure_box) {
                boolean isMeasuring = mPresenter.entryMeasureModel();
                dataBinding.llMeasureBox.setSelected(isMeasuring);
                dataBinding.llMeasureTool.setVisibility(isMeasuring ? View.VISIBLE : View.INVISIBLE);
            } else if (view.getId() == R.id.ll_history_box) {
                boolean isShowing = mPresenter.showOpHistoryDialog();
                dataBinding.llHistoryBox.setSelected(isShowing);
            } else if (view.getId() == R.id.ll_geo_undo) {
                mPresenter.doUndoGisOpHistory();
            } else if (view.getId() == R.id.ll_geo_redo) {
                mPresenter.doRedoGisOpHistory();
            }
        }


        public void mapControllerClick(View view) {
            if (mMapBoxMap == null) {
                return;
            }
            if (view.getId() == R.id.button_map_in) {
                mMapBoxMap.animateCamera(CameraUpdateFactory.zoomIn());
            }
            else if (view.getId() == R.id.button_map_out) {
                mMapBoxMap.animateCamera(CameraUpdateFactory.zoomOut());
            }
            if (view.getId() == R.id.button_location) {
                for (Layer layer : mMapBoxMap.getStyle().getLayers()) {
                    LogUtils.printError(layer.getId());
                }
            }
        }


        public void clickDrawType(View view) {
            if (view.getId() == R.id.ll_huizhi_box) {
                mPresenter.clickDrawType(DrawType.Huizhi);
            } else if (view.getId() == R.id.ll_bianjie_box) {
                mPresenter.clickDrawType(DrawType.Bianjie);
            } else if (view.getId() == R.id.ll_qiege_box) {
                mPresenter.clickDrawType(DrawType.Qiege);
            } else if (view.getId() == R.id.ll_wakong_box) {
                mPresenter.clickDrawType(DrawType.Wakong);
            } else if (view.getId() == R.id.ll_hebing_box) {
                mPresenter.clickDrawType(DrawType.Hebing);
            } else if (view.getId() == R.id.ll_shanchu_box) {
                mPresenter.clickDrawType(DrawType.Shanchu);
            }
        }


        public void clickToolOperation(View view) {
            if (view.getId() == R.id.ll_complete_box) {
                mPresenter.clickSaveOperation();
            } else if (view.getId() == R.id.ll_undo_box) {
                mPresenter.clickUndoOperation();
            } else if (view.getId() == R.id.ll_redo_box) {
                mPresenter.clickRedoOperation();
            } else if (view.getId() == R.id.ll_clear_box) {
                mPresenter.clickClearOperation();
            } else if (view.getId() == R.id.ll_cancel_box) {
                mPresenter.clickCloseOperation();
            } else if (view.getId() == R.id.ll_save_box) {
                mPresenter.clickSubmitOperation();
            }
        }

    }


    public class MeasureEventHandler {

        public void clickClose() {
            dataBinding.llMeasureBox.setSelected(false);
            dataBinding.llMeasureTool.setVisibility(View.INVISIBLE);
            mPresenter.closeMeasureModel();
        }

        public void clickDelete() {
            //清除正在标绘数据
            mPresenter.clickClearCurrentMeasure();
        }

        public void clickUnit() {
            mPresenter.clickMeasureUnit(getContext());
        }

        public void clickUndo() {
            mPresenter.clickUndoMeasure();
        }

        public void clickSave() {
            mPresenter.saveCurrentMeasure();
        }

    }


    public static final String KEY_ID = "id";
    public static final String KEY_VERSION_ID = "versionId";
    public static final String KEY_IS_LOCAL = "isLocal";
    public static Intent getStartIntent(Context context, String id, String versionId, boolean isLocal) {
        Intent intent = new Intent(context, GisMapActivity.class);
        intent.putExtra(KEY_ID, id);
        intent.putExtra(KEY_VERSION_ID, versionId);
        intent.putExtra(KEY_IS_LOCAL, isLocal);
        return intent;
    }


}